package com.lancoo.znbkxx.teacher.widget.bigimage

import android.content.Context
import android.widget.ImageView.ScaleType
import me.panpf.sketch.Sketch
import me.panpf.sketch.zoom.Sizes
import me.panpf.sketch.zoom.ZoomScales

class BigImageZoomer : ZoomScales {
    private val DEFAULT_MAXIMIZE_SCALE = 1.75f
    private val DEFAULT_MINIMUM_SCALE = 1.0f
    private val DEFAULT_DOUBLE_CLICK_ZOOM_SCALES =
        floatArrayOf(DEFAULT_MINIMUM_SCALE, DEFAULT_MAXIMIZE_SCALE)

    private var minZoomScale = DEFAULT_MINIMUM_SCALE
    private var maxZoomScale = DEFAULT_MAXIMIZE_SCALE
    private var doubleClickZoomScales = DEFAULT_DOUBLE_CLICK_ZOOM_SCALES // 双击缩放所使用的比例

    private var fullZoomScale = 0f
    private var fillZoomScale = 0f
    private var originZoomScale = 0f
    private var initZoomScale = 0f

    override fun reset(
        context: Context,
        sizes: Sizes,
        scaleType: ScaleType?,
        rotateDegrees: Float,
        readMode: Boolean
    ) {
        val drawableWidth =
            if (rotateDegrees % 180 == 0f) sizes.drawableSize.width else sizes.drawableSize.height
        val drawableHeight =
            if (rotateDegrees % 180 == 0f) sizes.drawableSize.height else sizes.drawableSize.width
        val imageWidth =
            if (rotateDegrees % 180 == 0f) sizes.imageSize.width else sizes.imageSize.height
        val imageHeight =
            if (rotateDegrees % 180 == 0f) sizes.imageSize.height else sizes.imageSize.width
        val widthScale = sizes.viewSize.width.toFloat() / drawableWidth
        val heightScale = sizes.viewSize.height.toFloat() / drawableHeight
        val imageThanViewLarge =
            drawableWidth > sizes.viewSize.width || drawableHeight > sizes.viewSize.height
        val finalScaleType: ScaleType?
        finalScaleType = if (scaleType == ScaleType.MATRIX) {
            ScaleType.FIT_CENTER
        } else if (scaleType == ScaleType.CENTER_INSIDE) {
            if (imageThanViewLarge) ScaleType.FIT_CENTER else ScaleType.CENTER
        } else {
            scaleType
        }

        // 小的是完整显示比例，大的是充满比例
        fullZoomScale = Math.min(widthScale, heightScale)
        fillZoomScale = Math.max(widthScale, heightScale)

        originZoomScale =
            Math.max(imageWidth.toFloat() / drawableWidth, imageHeight.toFloat() / drawableHeight)

        initZoomScale = getInitScale(context, sizes, finalScaleType!!, rotateDegrees, readMode)

        val sizeCalculator = Sketch.with(context).configuration.sizeCalculator
        if (readMode && sizeCalculator.canUseReadModeByHeight(imageWidth, imageHeight)) {
            // 阅读模式下保证阅读效果最重要
            minZoomScale = fullZoomScale
            maxZoomScale = Math.max(originZoomScale, fillZoomScale)
        } else if (readMode && sizeCalculator.canUseReadModeByWidth(imageWidth, imageHeight)) {
            // 阅读模式下保证阅读效果最重要
            minZoomScale = fullZoomScale
            maxZoomScale = Math.max(originZoomScale, fillZoomScale)
        } else if (finalScaleType == ScaleType.CENTER) {
            minZoomScale = 1.0f
            maxZoomScale = Math.max(originZoomScale, fillZoomScale)
        } else if (finalScaleType == ScaleType.CENTER_CROP) {
            minZoomScale = fillZoomScale
            // 由于CENTER_CROP的时候最小缩放比例就是充满比例，所以最大缩放比例一定要比充满比例大的多
            maxZoomScale = Math.max(originZoomScale, fillZoomScale * 1.5f)
        } else if (finalScaleType == ScaleType.FIT_START || finalScaleType == ScaleType.FIT_CENTER || finalScaleType == ScaleType.FIT_END) {
            minZoomScale = fullZoomScale

            // 如果原始比例仅仅比充满比例大一点点，还是用充满比例作为最大缩放比例比较好，否则谁大用谁
            maxZoomScale =
                if (originZoomScale > fillZoomScale && fillZoomScale * 1.2f >= originZoomScale) {
                    fillZoomScale
                } else {
                    Math.max(originZoomScale, fillZoomScale)
                }

            // 最大缩放比例和最小缩放比例的差距不能太小，最小得是最小缩放比例的1.5倍
            maxZoomScale = Math.max(maxZoomScale, minZoomScale * 1.5f)
        } else if (finalScaleType == ScaleType.FIT_XY) {
            minZoomScale = fullZoomScale
            maxZoomScale = fullZoomScale
        } else {
            // 基本不会走到这儿
            minZoomScale = fullZoomScale
            maxZoomScale = fullZoomScale
        }

        // 这样的情况基本不会出现，不过还是加层保险
        if (minZoomScale > maxZoomScale) {
            minZoomScale = minZoomScale + maxZoomScale
            maxZoomScale = minZoomScale - maxZoomScale
            minZoomScale = minZoomScale - maxZoomScale
        }

        // 双击缩放比例始终由最小缩放比例和最大缩放比例组成
        doubleClickZoomScales = floatArrayOf(minZoomScale, maxZoomScale)
    }

    private fun getInitScale(
        context: Context,
        sizes: Sizes,
        scaleType: ScaleType,
        rotateDegrees: Float,
        readMode: Boolean
    ): Float {
        val drawableWidth =
            if (rotateDegrees % 180 == 0f) sizes.drawableSize.width else sizes.drawableSize.height
        val drawableHeight =
            if (rotateDegrees % 180 == 0f) sizes.drawableSize.height else sizes.drawableSize.width
        val imageWidth =
            if (rotateDegrees % 180 == 0f) sizes.imageSize.width else sizes.imageSize.height
        val imageHeight =
            if (rotateDegrees % 180 == 0f) sizes.imageSize.height else sizes.imageSize.width
        val widthScale = sizes.viewSize.width.toFloat() / drawableWidth
        val heightScale = sizes.viewSize.height.toFloat() / drawableHeight
        val imageThanViewLarge =
            drawableWidth > sizes.viewSize.width || drawableHeight > sizes.viewSize.height
        val sizeCalculator = Sketch.with(context).configuration.sizeCalculator
        val finalScaleType: ScaleType
        finalScaleType = if (scaleType == ScaleType.MATRIX) {
            ScaleType.FIT_CENTER
        } else if (scaleType == ScaleType.CENTER_INSIDE) {
            if (imageThanViewLarge) ScaleType.FIT_CENTER else ScaleType.CENTER
        } else {
            scaleType
        }
        return if (readMode && sizeCalculator.canUseReadModeByHeight(imageWidth, imageHeight)) {
            //这里我开了阅读模式，并且重写了canUseReadModeByHeight 为true，所以，后面的都不会执行，只会进入到这个
//            widthScale
            heightScale
        } else if (readMode && sizeCalculator.canUseReadModeByWidth(imageWidth, imageHeight)) {
            heightScale
        } else if (finalScaleType == ScaleType.CENTER) {
            1.0f
        } else if (finalScaleType == ScaleType.CENTER_CROP) {
            //主要看这个
            Math.max(widthScale, heightScale)
        } else if (finalScaleType == ScaleType.FIT_START) {
            Math.min(widthScale, heightScale)
        } else if (finalScaleType == ScaleType.FIT_END) {
            Math.min(widthScale, heightScale)
        } else if (finalScaleType == ScaleType.FIT_CENTER) {
            Math.min(widthScale, heightScale)
        } else if (finalScaleType == ScaleType.FIT_XY) {
            1.0f
        } else {
            1.0f
        }
    }

    override fun getMinZoomScale(): Float {
        return 1f
    }

    override fun getMaxZoomScale(): Float {
        return 1f
    }

    override fun getInitZoomScale(): Float {
        return initZoomScale
    }

    override fun getFullZoomScale(): Float {
        return fullZoomScale
    }

    override fun getFillZoomScale(): Float {
        return fillZoomScale
    }

    override fun getOriginZoomScale(): Float {
        return originZoomScale
    }

    override fun getZoomScales(): FloatArray? {
        return doubleClickZoomScales
    }

    override fun clean() {
        originZoomScale = 1f
        fillZoomScale = originZoomScale
        fullZoomScale = fillZoomScale
        minZoomScale = DEFAULT_MINIMUM_SCALE
        maxZoomScale = DEFAULT_MAXIMIZE_SCALE
        doubleClickZoomScales = DEFAULT_DOUBLE_CLICK_ZOOM_SCALES
    }
}